package com.gugee.common.web.config.aspect;


import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.gugee.common.web.util.AspectUtil;
import com.gugee.common.web.util.Ret;
import com.xiguaji.boot.toolkit.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * 路由访问查看
 * @author zzy
 * @Date 2019-07-18 15:25
 */
@Slf4j
@Aspect
@Component
public class ControllerAspect {

    private LoadingCache<String,Boolean> cache = CacheBuilder.newBuilder().expireAfterAccess(2, TimeUnit.SECONDS).
            build(new CacheLoader<>() {
                @Override
                public Boolean load(String s){
                    return false;
                }
            });


    @Pointcut(value = "execution(* com.xiguaji..*.*Controller.*(..))")
    public void Pointcut(){
    }

    @Around(value = "Pointcut()")
    public Object printInfo(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        if(log.isDebugEnabled()){
            this.handle(proceedingJoinPoint);
        }

        if(!HttpUtil.getMethod().equals(RequestMethod.GET.name())){
            String key = getKey(proceedingJoinPoint);

            if(cacheGet(key)){
                // return Ret.noPermission("请不要重复操作");
                return Ret.noPermission("Don't take too many repetitions");
            }
            cachePut(key);
        }

        return proceedingJoinPoint.proceed();
    }

    private void handle(ProceedingJoinPoint point) {
        try{
            Method currentMethod = AspectUtil.INSTANCE.getMethod(point);
            String className = AspectUtil.INSTANCE.getClassName(point);
            StringBuffer sb = new StringBuffer();
            sb.append("\n============================================================================");
            sb.append("====================Controller Begin=================================================");
            sb.append("===============================================\n");
            sb.append("==  Method: {} \n");
            sb.append("==  IP: {} \n");
            sb.append("==  URL: {} \n");
            sb.append("==  RequestMethod: {} \n");
            sb.append("==  URL Params: {} \n");
            sb.append("==  AOP Params: {} \n");
            sb.append("============================================================================");
            sb.append("====================Controller End=================================================");
            sb.append("===============================================\n");
            log.debug(sb.toString(),className+"."+currentMethod.getName()+"()", HttpUtil.getIp(),HttpUtil.getRequestUrl(), HttpUtil.getMethod(),HttpUtil.getRequestParams(), point.getArgs());
        }catch (NoSuchMethodException nsme){
            nsme.printStackTrace();
            log.error("控制层跟踪出错！ 异常信息: {}",nsme.getMessage(),nsme);
        }
    }

    private String getKey(ProceedingJoinPoint point){
        StringBuffer stringBuffer = new StringBuffer(HttpUtil.getIp()).append("|");
        stringBuffer.append(HttpUtil.getRequestUrl()).append("|");
        stringBuffer.append(Arrays.toString(point.getArgs()));
        return stringBuffer.toString();
    }

    private void cachePut(String key){
        cache.put(key,true);
    }

    private boolean cacheGet(String key){
        try {
            return cache.get(key);
        } catch (ExecutionException e) {
            return false;
        }
    }
}
